'use strict';

angular.module('BaseServer')
.service('BaseModule', ['EntityService', 'BaseFunction', 'BaseEnum',
    function(EntityService, BaseFunction, BaseEnum) {
        var UIModule = function (scope, entityName) {
            this.EntityName = entityName;
            this.ChildModules = [];
            this.Condition = null;
            this.OrderBy = null;
            this.Populate = "";
            this.LoadMode = BaseEnum.LoadMode.NoCacheAndPaging;   //数据加载模式
            this._Filtration = null;      //Module层过滤条件

            //Handle
            this.AfterOnLoad = null;        //数据载入后的方法，可以在显示之前改变数据
            this.AfterOnAdd = null;         //新增记录后，显示之前改变数据，可用来设置默认值                     

            this._ID = BaseFunction.getGuid();                       //module在当前页面中的唯一ID
            this._NewRecordID = -1;         //新增记录ID
            this._ParentModule = null;
            this._Scope = scope;
            this._FocusedRecord = null;
            this._Records = [];
            this._PageSize = 1;
            this._IsEntityModule = true;    //是否是实体Module

            if(entityName.substring(0, 1) == "_"){
                this._IsEntityModule = false;
                this.PageSize = 10;
            }
        };

        UIModule.prototype = {
            get ParentModule(){
                return this._ParentModule;
            },
            set ParentModule(parentModule){
                this._ParentModule = parentModule;
                this._ParentModule.ChildModules.push(this);

                var self = this;
                this.Scope.$watch('Module.' + parentModule.EntityName + '.FocusedRecord._id',
                    function (newValue, oldValue, scope) {
                        if (newValue != oldValue) {
                            if (parentModule.FocusedRecord != null && parentModule.FocusedRecord.RowStatus != BaseEnum.RowStatus.Insert.Value) {
                                if(self.Condition == null){
                                    self.Condition = {};
                                }
                                self.Condition[parentModule.EntityName] = parentModule.FocusedRecord._id;
                                self.load();
                            }
                            else{
                                self.Records = [];
                                self.emitOnLoadEvent([]);
                            }
                        }
                    },
                    false
                );
            },
            get ID(){
                return this._ID;
            },
            get IsEntityModule(){
                return this._IsEntityModule;
            },
            get NewRecordID(){
                return this._NewRecordID--;
            },
            set NewRecordID(val){
                if(this._NewRecordID != val){
                    this._NewRecordID = val;
                }
            },
            get Scope(){
                return this._Scope;
            },
            get FocusedRecord(){
                return this._FocusedRecord;
            },
            set FocusedRecord(val){
                if(this._FocusedRecord != val){
                    this._FocusedRecord = val;
                }
            },
            get Records(){
                var records = [];
                for(var i=0; i<this._Records.length; i++){
                    if(this._Records[i].RowStatus != BaseEnum.RowStatus.Delete.Value && !this._Records[i].IsHide){
                        if(this.Filtration == null){
                            records.push(this._Records[i]);
                        }
                        else{
                            var isMatch = true;
                            var record = this._Records[i];
                            for(var j=0; j<this.Filtration.length; j++){
                                try{
                                    isMatch = eval(this.Filtration[j]);
                                }
                                catch(e){
                                    isMatch = false;
                                }
                                if(!isMatch){
                                    break;
                                }
                            }
                            if(isMatch){
                                records.push(this._Records[i]);
                            }
                        }
                    }
                }
                return records;
            },
            set Records(val){
                if(val == null){
                    val = new Array();
                }
                this._Records = val;
            },
            get CacheRecords(){
                return this._Records;
            },
            get SelectedRecords(){
                var selectRecords = [],
                    records = this.Records;
                for(var i=0; i<records.length; i++){
                    if(records[i].IsSelected && records[i].RowStatus != BaseEnum.RowStatus.Delete.Value){
                        selectRecords.push(records[i]);
                    }
                }
                return selectRecords;
            },
            get PageSize(){
                return this._PageSize;
            },
            set PageSize(val){
                this._PageSize = val;
                if(this._PageSize == 1){
                    this.LoadMode = BaseEnum.LoadMode.NoCacheAndPaging;
                }
                else
                {
                    if(!this.IsEntityModule){
                        this.LoadMode = BaseEnum.LoadMode.CacheAndNoPaging;
                    }
                    else if(this.LoadMode == BaseEnum.LoadMode.NoCacheAndPaging){
                        this.LoadMode = BaseEnum.LoadMode.CacheAndPaging;
                    }
                }
            }, 
            get Filtration(){
                return this._Filtration;
            },
            set Filtration(val){
                if(val != null && val.constructor == Array && val.length > 0){
                    this._Filtration = val;
                }
                else{
                    this._Filtration = null;
                }
            },

            //从数据库提取数据方法
            load: function(condition, orderBy, completeFun){
                if(this.IsEntityModule){
                    if(condition == undefined || condition == null) {
                        condition = this.Condition;
                    }
                    if(orderBy == undefined || orderBy == null) {
                        orderBy = this.OrderBy;
                    }

                    this.FocusedRecord = null;
                    this._Records = new Array();

                    var self = this;
                    if(this.LoadMode == BaseEnum.LoadMode.CacheAndNoPaging){
                        this.loadAll(condition, orderBy,
                            function(records){
                                self.emitOnLoadEvent(records);
                                if(completeFun != undefined && completeFun != null) {
                                    completeFun(self.Records);
                                }
                            }
                        );
                    }
                    else if(this.LoadMode == BaseEnum.LoadMode.CacheAndPaging || this.LoadMode == BaseEnum.LoadMode.NoCacheAndPaging){
                        self.loadByPage(condition, orderBy, 0, null, 
                            function (records) {
                                self.emitOnLoadEvent(records);
                                if (completeFun != undefined && completeFun != null) {
                                    completeFun(records);
                                }
                            }
                        );
                    }
                }
            },
            loadAll: function(condition, orderBy, completeFun){
                if(this.IsEntityModule){
                    if(condition == undefined || condition == null){
                        condition = this.Condition;
                    }
                    if(orderBy == undefined || orderBy == null){
                        orderBy = this.OrderBy;
                    }

                    this._Records = new Array();
                    var self = this;

                    BaseFunction.loading(true);
                    this.find(condition, orderBy, this.Populate,
                        function (records) {
                            self._Records = records;                            
                            if(self.AfterOnLoad){
                                self.AfterOnLoad(self.Records);
                            }
                            if(completeFun != undefined && completeFun != null) {
                                completeFun(records);
                            }
                            BaseFunction.loading(false);
                        }
                    );
                }
            },
            loadByPage: function(condition, orderBy, pageNum, pageSize, completeFun){
                if(this.IsEntityModule){
                    if(condition == undefined || condition == null){
                        condition = this.Condition;
                    }
                    if(orderBy == undefined || orderBy == null){
                        orderBy = this.OrderBy;
                    }
                    if(pageNum == undefined || pageNum == null){
                        pageNum = 0;
                    }
                    if(pageSize == undefined || pageSize == null){
                        pageSize = this.PageSize;
                    }

                    BaseFunction.loading(true);

                    var self = this;
                    EntityService.pageQuery(self.EntityName, condition, orderBy, self.Populate,
                        pageNum, pageSize,
                        function(records){
                            for(var i=0; i<records.length; i++){
                                records[i].RowStatus = BaseEnum.RowStatus.UnChange.Value;
                                records[i].IsSelected = false;
                                records[i].IsHide = false;
                            }

                            if(self.LoadMode == BaseEnum.LoadMode.CacheAndPaging){
                                self._Records = self._Records.concat(records);
                            }
                            else if(self.LoadMode == BaseEnum.LoadMode.NoCacheAndPaging){
                                self._Records = records;
                            }

                            if(self.AfterOnLoad){
                                self.AfterOnLoad(records);
                            }
                            if(completeFun != undefined && completeFun != null) {
                                completeFun(records);
                            }
                            BaseFunction.loading(false);
                        }
                    );
                }
            },
            findById: function(id, completeFun){
                if(this.IsEntityModule){
                    EntityService.findById(this.EntityName, id, this.Populate,
                        function (record) {
                            if(record != null){
                                record.RowStatus = BaseEnum.RowStatus.UnChange.Value;
                                record.IsSelected = false;
                                record.IsHide = false;
                            }

                            if(completeFun != undefined && completeFun != null) {
                                
                                completeFun(record);
                            }
                        }
                    );
                }
            },
            find: function(condition, orderBy, populate, completeFun){
                if(this.IsEntityModule){
                    EntityService.find(this.EntityName, condition, orderBy, populate,
                        function (records) {
                            if (records.length > 0) {
                                for (var i = 0; i < records.length; i++) {
                                    records[i].RowStatus = BaseEnum.RowStatus.UnChange.Value;
                                    records[i].IsSelected = false;
                                    records[i].IsHide = false;
                                }
                            }

                            if(completeFun != undefined && completeFun != null) {
                                completeFun(records);
                            }
                        }
                    );
                }
            },
            findRecordIndex: function(record, completeFun){
                var self = this;
                if(this.IsEntityModule){
                    if(record.RowStatus != BaseEnum.RowStatus.Insert.Value){
                        EntityService.findRecordIndex(this.EntityName, record._id, this.Condition, this.OrderBy,
                            function(recordIndex){
                                if(completeFun != undefined && completeFun != null) {
                                    completeFun(recordIndex);
                                }
                            }
                        );
                    }
                    else{
                        if(completeFun != undefined && completeFun != null) {
                            completeFun(null);
                        }
                    }
                }
            },
            search: function(text, limit, completeFun){
                if(text.trim() == ""){
                    return;
                }
                if(limit == undefined){
                    limit = null;
                }
                EntityService.search(this.EntityName, text, this.Condition, limit, function(records){
                    completeFun(records.Data);
                });
            },
            distinct: function(field, condition){
                return EntityService.distinct(this.EntityName, field, condition);
            },
            aggregate: function(args, completeFun){
                return EntityService.aggregate(this.EntityName, args);
            },
            mapReduce: function(option, condition, orderBy){
                return EntityService.mapReduce(this.EntityName, option, condition, orderBy);
            },

            //持久化方法
            save: function (successFun, errFunction) {
                if(this.IsEntityModule){
                    var self = this;
                    if(this.PageSize == 1) {
                        if(this.FocusedRecord != null && this.FocusedRecord.RowStatus != BaseEnum.RowStatus.UnChange.Value) {
                            var recording = [];     //记录ref的值，因为保存之后不会返回来
                            if(this.Populate !== ''){
                                if(this.Populate.constructor === Object){
                                    if(this.FocusedRecord[this.Populate.path] != undefined && 
                                        this.FocusedRecord[this.Populate.path] != null && 
                                        this.FocusedRecord[this.Populate.path] != ""){
                                        var strPath = this.Populate.path;
                                        recording.push({FieldName : strPath, Value: this.FocusedRecord[strPath]});
                                    }
                                }
                                else if(this.Populate.constructor === Array){
                                    for(var i=0; i<this.Populate.length; i++){
                                        if(this.FocusedRecord[this.Populate[i].path] != undefined && 
                                            this.FocusedRecord[this.Populate[i].path] != null && 
                                            this.FocusedRecord[this.Populate[i].path] != ""){
                                            var strPath = this.Populate[i].path;
                                            recording.push({FieldName : strPath, Value: this.FocusedRecord[strPath]});
                                        }
                                    }
                                }
                                else if(this.Populate.constructor === String){
                                    var strPopulates = this.Populate.trim().replace(/  /g, " ").split(" ");
                                    for(var i=0; i<strPopulates.length; i++){
                                        if(this.FocusedRecord[strPopulates[i]] != undefined && 
                                            this.FocusedRecord[strPopulates[i]] != null && 
                                            this.FocusedRecord[strPopulates[i]] != ""){
                                            var strPath = strPopulates[i];
                                            recording.push({FieldName : strPath, Value: this.FocusedRecord[strPath]});
                                        }
                                    }
                                }
                            }

                            var record = Object.assign({}, this.FocusedRecord);
                            delete record.IsSelected;
                            delete record.IsHide;
                            EntityService.save(this.EntityName, [record], function (data) {
                                BaseFunction.tip("保存完成");
                                data.IsSelected = self.FocusedRecord.IsSelected;
                                data.IsHide = self.FocusedRecord.IsHide;
                                for(var i=0; i<recording.length; i++){
                                    data[recording[i].FieldName] = recording[i].Value;
                                }
                                data.RowStatus = BaseEnum.RowStatus.UnChange.Value;
                                if(self.AfterOnLoad){
                                    self.AfterOnLoad([data]);
                                }
                                self.FocusedRecord = data;

                                self.emitSaveEvent();
                                if (successFun != undefined) {
                                    successFun(self.FocusedRecord);
                                }
                            },
                            errFunction);
                        }
                        else{
                            if (successFun != undefined) {
                                successFun(self.FocusedRecord);
                            }
                        }
                    }
                    else {
                        var saveRecords = new Array();
                        for(var i=0; i<this._Records.length; i++){
                            if(this._Records[i].RowStatus != BaseEnum.RowStatus.UnChange.Value){
                                var record = Object.assign({}, this._Records[i]);
                                delete record.IsSelected;
                                delete record.IsHide;
                                saveRecords.push(record);
                            }
                        }

                        if(saveRecords.length > 0) {
                            EntityService.save(this.EntityName, saveRecords,
                                function (data) {
                                    BaseFunction.tip("保存成功");
                                    self.emitSaveEvent();
                                    if(successFun != undefined){
                                        successFun(data);
                                    }
                                }
                            );
                        }
                        else{
                            if (successFun != undefined) {
                                successFun([]);
                            }
                        }
                    }
                }
            },
            updateByValue: function(condition, value, completeFun){
                if(condition == null || condition == undefined){
                    condition = {_id: this.FocusedRecord._id};
                }
                EntityService.updateByValue(this.EntityName, condition, value, function(result){
                    if(completeFun){
                        completeFun(result);
                    }
                });
            },

            add: function(recordIndex){
                if(this.PageSize == 1){
                    this._Records = new Array();
                }

                var newRecord = {
                    _id: this.NewRecordID--,
                    RowStatus: BaseEnum.RowStatus.Insert.Value,
                    IsSelected: false,
                    IsHide: false
                };

                if(this.ParentModule != null){
                    if(this.ParentModule.FocusedRecord != null) {
                        newRecord[this.ParentModule.EntityName]= this.ParentModule.FocusedRecord._id;
                    }
                }
                if(recordIndex != undefined){
                    recordIndex = this._Records.indexOf(this.Records[recordIndex]);

                    if(recordIndex < this.Records.length){
                        this._Records.splice(recordIndex, 0, newRecord);
                    }
                    else{
                        this._Records.push(newRecord);
                    }
                }
                else {
                    this._Records.push(newRecord);
                }
                
                if(this.PageSize == 1){
                    this.FocusedRecord = newRecord;
                }

                if(this.AfterOnAdd){
                    this.AfterOnAdd(newRecord);
                }
                return newRecord;
            },
            delete: function(completeFun){
                if (this.PageSize == 1) {
                    var focusedRecord = this.FocusedRecord;
                    if (this.FocusedRecord.RowStatus == BaseEnum.RowStatus.Insert.Value) {
                        this._Records = [];
                        this.FocusedRecord = null;

                        if(completeFun != undefined && completeFun != null) {
                            completeFun();
                        }
                        this.emitDeleteEvent([focusedRecord]);
                    }
                    else{
                        if(this.IsEntityModule){
                            var self = this;
                            this.FocusedRecord.RowStatus = BaseEnum.RowStatus.Delete.Value;
                            EntityService.delete(this.EntityName, this.FocusedRecord,
                                function (data) {
                                    self._Records = [];
                                    self.FocusedRecord = null;
                                    BaseFunction.tip("删除完成");

                                    if(completeFun) {
                                        completeFun();
                                    }
                                    
                                    self.emitDeleteEvent([focusedRecord]);
                                }
                            );
                        }
                    }
                }
                else {
                    this.deleteRecord(this.FocusedRecord);

                    if(completeFun != undefined && completeFun != null) {
                        completeFun();
                    }
                }
            },
            cancel: function(afterCancel){
                if(this.PageSize == 1) {
                    if(this.FocusedRecord.RowStatus == BaseEnum.RowStatus.Insert.Value){
                        this._Records = [];
                        this.FocusedRecord = this.add();

                        if(afterCancel != undefined){
                            afterCancel();
                        }
                    }
                    else{
                        var self = this;
                        this.findById(this.FocusedRecord._id, function(record){
                            self.FocusedRecord = record;

                            if(afterCancel != undefined){
                                afterCancel();
                            }
                        });
                    }
                }
                else{
                    this.FocusedRecord = null;
                    if(this.EntityName.substring(0,1) == "_"){
                        this._Records = [];
                        if(afterCancel != undefined){
                            afterCancel();
                        }
                    }
                    else{
                        this._Records = [];
                        this.load(null, null, function(){
                            if(afterCancel != undefined){
                                afterCancel();
                            }
                        });
                    }
                }
            },
            //争对列表的批量删除并持久化数据库
            deleteSelecteds: function(completeFun){
                if(this.IsEntityModule){
                    var selectRecords = this.SelectedRecords;
                    var ids = [];
                    for(var i=0; i <selectRecords.length; i++){
                        ids.push(selectRecords[i]._id);
                    }

                    var self = this;
                    EntityService.deleteByIds(this.EntityName, ids,
                        function (data) {
                            BaseFunction.tip("批量删除完成");
                            var result = data;
                            for(var i=0; i<selectRecords.length; i++){
                                self._Records.splice(self._Records.indexOf(selectRecords[i]), 1);
                            }
                            if(completeFun) {
                                completeFun();
                            }
                            self.emitDeleteEvent(selectRecords);
                        },
                        function(err){
                            BaseFunction.alert(err.data.message, err.data.title);
                        }
                    );
                }
            },

            //module层的数据操作方法
            deleteRecord: function(record){
                if(this.FocusedRecord != null && this.FocusedRecord._id == record._id){
                    this.FocusedRecord = null;
                }

                var recordIndex = this._Records.indexOf(record);
                if (record.RowStatus == BaseEnum.RowStatus.Insert.Value) {
                    if (recordIndex > -1) {
                        this._Records.splice(recordIndex, 1);
                    }
                }
                else {
                    record.RowStatus = BaseEnum.RowStatus.Delete.Value;
                }
            },
            deleteRecords: function(records){
                for(var i=0; i<records.length; i++){
                    this.deleteRecord(records[i]);
                }
            },
            removeRecord: function(record){
                this._Records.splice(this._Records.indexOf(record), 1);
            },
            getRecordIndex: function(record){
                return this.Records.indexOf(record);
            },
            findRecords: function (condition) {
                var results = new Array();
                var records = this.Records;

                for (var i = 0; i < records.length; i++) {
                    var isMatch = true;

                    if(condition != undefined && condition != null) {
                        for (var name in condition) {
                            if (records[i][name] != condition[name]) {
                                isMatch = false;
                                break;
                            }
                        }

                        if (isMatch) {
                            results.push(records[i]);
                        }
                    }
                }

                return results;
            },
            findRecordById: function(id){
                var records = this.Records;
                for (var i = 0; i < records.length; i++) {
                    if(records[i]._id == id){
                        return records[i];
                    }
                }

                return null;
            },
            sort: function(orderBy){
                if(orderBy == undefined || orderBy == null){
                    orderBy = this.OrderBy;
                }

                this._Records.sort(function (a, b) {
                    for (var name in orderBy) {
                        var val1 = eval("a." + name),
                            val2 = eval("b." + name);
                        if(val1 && val1.constructor == Object){
                            val1 = val1._id;
                        }
                        if(val2 && val2.constructor == Object){
                            val2 = val2._id;
                        }

                        if(orderBy[name] > 0){
                            if (val1 > val2) {
                                return 1;
                            }
                            else if (val1 < val2) {
                                return -1;
                            }
                        }
                        else{
                            if (val1 > val2) {
                                return -1;
                            }
                            else if (val1 < val2) {
                                return 1;
                            }
                        }
                    }
                    return 1;
                });
            },

            //数据保存完毕，通知DataGrid
            emitSaveEvent: function(){
                this.Scope.$broadcast("SaveEvent" + this.ID);
            },
            //删除并保存完成
            emitDeleteEvent: function(records){
                this.Scope.$broadcast("DeleteEvent" + this.ID, records);
            },
            //数据载入完成
            emitOnLoadEvent: function(){
                this.Scope.$broadcast("OnLoadEvent" + this.ID);
            },

            //手动通知DataGrid重新加载数据
            emitReloadEvent: function(){
                this.Scope.$broadcast("ReloadEvent" + this.ID);
            },
            // 手动改变Grid行数据，需要刷新使用
            emitRowsDataChangeEvent: function(records){
                if(records == undefined){
                    records = [this.FocusedRecord];
                }
                this.Scope.$broadcast("RowsDataChangeEvent" + this.ID, records);
            },
            // 手动删除行，需要刷新
            emitRowsDeleteEvent: function(records){
                if(records == undefined){
                    records = [];
                }
                this.Scope.$broadcast("RowsDeleteEvent" + this.ID, records);
            },
            // 手动全部刷新
            emitRefreshEvent: function(){
                this.Scope.$broadcast("RefreshEvent" + this.ID);
            },
            // 手动刷新当前页
            emitRefreshCurrentPageEvent: function(){
                this.Scope.$broadcast("RefreshCurrentPageEvent" + this.ID);
            }
        };

        return {
            //scope: 必输项，作用域
            //moduleName 必输项，文档名称
            //entityName 实体名称，默认为moduleName，如果前面带"_"则为自定义Module，不是实体Module
            initModule: function (scope, moduleName, entityName) {
                if (scope == null || scope == undefined) {
                    BaseFunction.alert("scope 不能为空", "创建Module错误");
                }
                if (moduleName == null || moduleName == undefined) {
                    BaseFunction.alert("moduleName 不能为空", "创建Module错误");
                }
                if(entityName == undefined){
                    entityName = moduleName;
                }
                var newModule = new UIModule(scope, entityName);

                if(scope.Module == undefined || scope.Module == null){
                    scope.Module = {
                        save: function(successFun) {
                            var saveDatas = new Array();
                            for (var module in this) {
                                if(this[module].Records.length > 0){
                                    var saveRecords = [];
                                    for(var i=0; i<this[module].Records.length; i++){
                                        if(this[module].Records[i].RowStatus != BaseEnum.RowStatus.UnChange.Value){
                                            saveRecords.push(this[module].Records[i]);
                                        }
                                    }
                                    saveRecords = saveRecords.concat(this[module]._DeleteRecords);
                                    var moduleData = {
                                        EntityName: module,
                                        Records: saveRecords
                                    };
                                    saveDatas.push(moduleData);
                                }
                            }

                            if(saveDatas.length > 0){
                                EntityService.saves(saveDatas, function (data) {
                                    if(successFun != undefined){
                                        successFun();
                                    }
                                });
                            }
                        }
                    };
                }

                eval('scope.Module.' + moduleName + ' = newModule');

                scope.$watch('Module.' + moduleName + '.FocusedRecord',
                    function (newValue, oldValue, scope) {
                        if (newValue != null && oldValue != null && newValue._id == oldValue._id 
                            && newValue.RowStatus == oldValue.RowStatus && newValue.IsSelected == oldValue.IsSelected) {
                            if (newValue.RowStatus == BaseEnum.RowStatus.UnChange.Value) {
                                eval('scope.Module.' + moduleName + '.FocusedRecord.RowStatus = BaseEnum.RowStatus.Modify.Value');
                            }
                        }
                    },
                    true
                );

                return newModule;
            }
        }
    }
]);